/*
 * Copyright (C) 2012 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.facebook.swift.codec.metadata;

import com.facebook.swift.codec.metadata.ThriftCatalog;
import com.facebook.swift.codec.metadata.ThriftFieldMetadata;
import com.facebook.swift.service.metadata.ThriftMethodMetadata;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import net.gdface.utils.ClassCommentProvider;

import java.lang.reflect.Method;
import java.util.List;

import static com.facebook.swift.codec.metadata.DecoratorThriftServiceMetadata.javadocCommentProviderFactory;

/**
 * 重载{@link #getParameters()}方法,用{@link DecoratorThriftFieldMetadata}替换{@link ThriftFieldMetadata}
 * @author guyadong
 *
 */
@Immutable
public class DecoratorThriftMethodMetadata extends ThriftMethodMetadata
{
	private volatile ClassCommentProvider commentProvider;
	private volatile ImmutableList<String> documentation ;
    public DecoratorThriftMethodMetadata(String serviceName, Method method, ThriftCatalog catalog){
    	super(serviceName, method, catalog);
    }
    /** 
     * {@link DecoratorThriftFieldMetadata}缓存对象,
     * 保存每个{@link ThriftFieldMetadata}对应的{@link DecoratorThriftFieldMetadata}实例 
     */
    private final LoadingCache<ThriftFieldMetadata,DecoratorThriftFieldMetadata> 
    	FIELDS_CACHE = 
    		CacheBuilder.newBuilder().build(
    				new CacheLoader<ThriftFieldMetadata,DecoratorThriftFieldMetadata>(){
						@Override
						public DecoratorThriftFieldMetadata load(ThriftFieldMetadata key) throws Exception {
							return new DecoratorThriftFieldMetadata(key)
									.setJavadocCommentProvider(getCommentProvider())
									.setOwnedMethod(getMethod());
						}});
    /**  将{@link ThriftFieldMetadata}转换为 {@link DecoratorThriftFieldMetadata}对象 */
	private final Function<ThriftFieldMetadata,ThriftFieldMetadata> 
		FIELD_TRANSFORMER = 
			new Function<ThriftFieldMetadata,ThriftFieldMetadata>(){
				@Nullable
				@Override
				public ThriftFieldMetadata apply(@Nullable ThriftFieldMetadata input) {
				    return null == input || input instanceof DecoratorThriftFieldMetadata  
				    		? input 
				    		: FIELDS_CACHE.getUnchecked(input);
				}};
    @Override
    public List<ThriftFieldMetadata> getParameters()
    {
        return Lists.transform(super.getParameters(), FIELD_TRANSFORMER);
    }

	public ErpcType getErpcReturnType() {
		return ErpcType.getErpcType(super.getReturnType());
	}

	@Override
	public ImmutableList<String> getDocumentation() {
		// double checking
		if(documentation == null){
			synchronized (this) {
				if(documentation == null){
					documentation = super.getDocumentation();
					if(javadocCommentProviderFactory != null){
						if(documentation == null || documentation.isEmpty()){
							documentation = getCommentProvider().commentOfMethod(getMethod());
						}
					}
				}
			}
		}
		return documentation;
	}
	
	private ClassCommentProvider getCommentProvider(){
		if(commentProvider == null){
			synchronized (this) {
				if(commentProvider == null){
					commentProvider = javadocCommentProviderFactory  != null  
							? javadocCommentProviderFactory.apply(getMethod().getDeclaringClass()) 
							: null;
				}
			}
		}
		return commentProvider;
	}
}
